package com.element.oauth2.server.global.generator;

import com.common.core.utils.MDFiveUtil;
import com.element.oauth2.constant.SecurityParams;
import org.springframework.lang.Nullable;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.server.authorization.OAuth2Authorization;
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenGenerator;
import org.springframework.util.CollectionUtils;

import java.time.Instant;
import java.util.Collections;
import java.util.Set;

/**
 * 自定义Token生成规则
 */
public class OAuthAccessTokenGenerator implements OAuth2TokenGenerator<OAuth2AccessToken> {

    private final OAuth2AuthorizationService oAuth2AuthorizationService;

    public OAuthAccessTokenGenerator(OAuth2AuthorizationService oAuth2AuthorizationService) {
        this.oAuth2AuthorizationService = oAuth2AuthorizationService;
    }

    @Nullable
    @Override
    public OAuth2AccessToken generate(OAuth2TokenContext context) {
        if (!OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
            return null;
        } else {
            OAuth2Authorization authorization = context.getAuthorization();
            // 刷新token逻辑,删除已存在的
            if (null != authorization) {
                oAuth2AuthorizationService.remove(authorization);
            }
            String accessToken = "T" + MDFiveUtil.getOnlyId();
            // 获取当前人有无授权信息
            RegisteredClient registeredClient = context.getRegisteredClient();
            AuthorizationGrantType grantType = context.get(AuthorizationGrantType.class);
            if (null != registeredClient && null != grantType) {
                String key = SecurityParams.SPRING_SECURITY_USER_TOKEN_KEY(registeredClient.getClientId(), grantType.getValue(), context.getPrincipal().getName());
                OAuth2Authorization oAuth2Authorization = oAuth2AuthorizationService.findById(key);
                if (null != oAuth2Authorization) {
                    accessToken = oAuth2Authorization.getAccessToken().getToken().getTokenValue();
                }
            }
            // 生成新的token
            Instant issuedAt = Instant.now();
            Instant expiresAt = issuedAt.plus(context.getRegisteredClient().getTokenSettings().getAccessTokenTimeToLive());
            Set<String> scopes = context.getRegisteredClient().getScopes();
            if (CollectionUtils.isEmpty(scopes)) {
                scopes = Collections.emptySet();
            }
            return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, accessToken, issuedAt, expiresAt, scopes);
        }
    }
}